package jp.co.kayo.gae.takidashibot.utils;

import java.util.logging.Level;
import java.util.logging.Logger;

import jp.co.kayo.gae.takidashibot.meta.TwitterStateMeta;
import jp.co.kayo.gae.takidashibot.model.TwitterState;

import org.slim3.datastore.Datastore;
import org.slim3.memcache.Memcache;
import com.google.appengine.api.datastore.Transaction;

import twitter4j.IDs;
import twitter4j.Paging;
import twitter4j.ResponseList;
import twitter4j.Status;
import twitter4j.StatusUpdate;
import twitter4j.Twitter;
import twitter4j.TwitterException;
import twitter4j.User;


public class TwitterClient {
    private static final boolean debug = true;
    private static final Logger log = Logger.getLogger(TwitterClient.class
        .getName());
    
    private static final long WAITMSEC = 5000;
    
    public boolean keepwait;

    private Twitter twitter;
    
    private String screen_name;
    
    public TwitterClient(Twitter twitter, String screen_name){
        this.twitter = twitter;
        this.screen_name = screen_name;
        keepwait = false;
    }
    
    public String getScreenName(){
        return screen_name;
    }
    
    public Long getLastProc(){
        Long ret = Memcache.get(getScreenName()+".lastproc");
        if(ret == null){
            TwitterStateMeta tm = TwitterStateMeta.get();
            TwitterState obj = Datastore.query(tm).filter(tm.screen_name.equal(getScreenName())).asSingle();
            if(obj != null){
                ret = obj.getLastproc();
                Memcache.put(getScreenName()+".lastproc", ret);
            }
        }
        return ret;
    }
    
    public void setLastProc(long t){
        Memcache.put(getScreenName()+".lastproc", t);
        
        TwitterStateMeta tm = TwitterStateMeta.get();
        TwitterState obj = Datastore.query(tm).filter(tm.screen_name.equal(getScreenName())).asSingle();
        Transaction tx = null;
        try{
            if(obj != null){
                tx = Datastore.beginTransaction();
                obj.setLastproc(t);
                Datastore.put(obj);
                tx.commit();
            }
            else{
                tx = Datastore.beginTransaction();
                obj = new TwitterState();
                obj.setScreen_name(getScreenName());
                obj.setLastproc(t);
                Datastore.put(obj);
                tx.commit();
            }
        }
        finally{
            if (tx!= null && tx.isActive()){
                tx.rollback();
            }
        }
    }
    
    private void keepWait(){
        if(!debug){
            if(keepwait){
                try {
                    Thread.sleep(WAITMSEC);
                } catch (InterruptedException e) {
                }
            }
            keepwait = true;
        }
    }
    
    
    public Status updateState(StatusUpdate update) throws TwitterException{
        keepWait();
        if(debug){
            log.log(Level.INFO,"updateStatus=" + update.getStatus());
            return null;
        }
        else{
            return twitter.updateStatus(update);
        }
    }
    
    public void say(StatusUpdate update) {
        keepWait();
        if(debug){
            log.log(Level.INFO,"say=" + update.getStatus());
        }
        else{
            try{
                twitter.updateStatus(update);
            }
            catch(Exception e){
                log.log(Level.WARNING, "say", e);
            }
        }
    }
    
    public Status destroyStatus(long id) throws TwitterException{
        if(debug){
            log.log(Level.INFO,"destroyStatus=" + id);
            return null;
        }
        else{
            return twitter.destroyStatus(id);
        }
    }
    
    public ResponseList<Status> getHomeTimeline() throws TwitterException{
        return twitter.getHomeTimeline();
    }
    
    public User createFriendship(long id) throws TwitterException{
        return twitter.createFriendship(id);
    }
    
    public User destroyFriendship(long id) throws TwitterException{
        return twitter.destroyFriendship(id);
    }
    
    public IDs getFollowersIDs(long id) throws TwitterException{
        return twitter.getFollowersIDs(id);
    }
    
    public IDs getFriendsIDs(long id) throws TwitterException{
        return twitter.getFriendsIDs(id);
    }
    
    public ResponseList<Status> getUserTimeline(String s) throws TwitterException{
        return twitter.getUserTimeline(s); 
    }
    
    public ResponseList<Status> getUserTimeline(String s, Paging p) throws TwitterException{
        return twitter.getUserTimeline(s, p); 
    }
    
    
    public ResponseList<User> lookupUsers(IDs ids) throws TwitterException{
        return twitter.lookupUsers(ids.getIDs());
    }
    
    public ResponseList<Status> getMentions() throws TwitterException{
        return twitter.getMentions();
    }
}
